
#include <algorithm>
#include <cassert>

#include "text_socket.h"

using namespace sock;

TextSocket::TextSocket(sock::ClientSocket &other):ClientSocket( other )
{

}


bool TextSocket::writeln(const std::string &line)
{
	ClientSocket::write( line.data(), line.size() );
	ClientSocket::write( "\r\n", 2 );
	return true;
}
/*
int TextSocket::read(void *buf, int len)
{
	int copied = min( len, _buf.size() );
	
	std::copy( _buf.begin(), _buf.begin() + copied, reinterpret_cast<char*>(buf) );
	_buf.erase( _buf.begin(), _buf.begin() + copied );

	int read_len = 0;
	int rest = len - copied;
	while ( rest > 0 ){
		char buf[1024];
		read_len = RawSocket::read( buf, 1024 );
		std::copy( buf, buf + min(rest, read_len), std::back_inserter( _buf ) );
		copied += min( rest, read_len );
		rest = len - copied;
	}
	if( copied == read_len ){
		std::copy( reinterpret_cast<char*>(buf) + rest, reinterpret_cast<char*>(buf) + read_len, std::back_inserter(_buf) );
	}
	return copied;
}
*/
void TextSocket::readln(std::string *pstring)
{
	typedef std::deque<char>::iterator Iter;

	std::string newline; // will contain upon spliting trailing \r\n
	unsigned state = 0; // 0,1,2 consecutive line end symbols found "\r\n"
	bool sock_closed_flag = false;
	while( state != 2 && !sock_closed_flag ){
		switch( state ) 
		{
		case 0:
			{
				Iter it = std::find( _buf.begin(), _buf.end(), '\r' );
				if( it == _buf.end() ){
					newline.append( _buf.begin(), _buf.end() );
					_buf.clear();
					feed_buf();
				} else {
					newline.append( _buf.begin(), it + 1 );
					_buf.erase( _buf.begin(), it+1 );
					state = 1;
				}
			}
			break;
		case 1:
			{
				Iter it = _buf.begin();
				if( it != _buf.end() ){
					if( *it == '\n' ){
						state = 2;
						_buf.erase( _buf.begin() );
					} else {
						state = 0;
					}
				} else {
					newline.append( _buf.begin(), _buf.end() );
					_buf.clear();
					feed_buf();
				}
			}
			break;
		case 2:
			// found \r\n
			// never reached.
			assert( false );
			break;
		}
	}

	if( pstring != NULL ){
		pstring->assign( newline, 0, newline.size() - 1 );
	}

}

void TextSocket::feed_buf()
{
	char buf[100];
	size_t len = ClientSocket::read( buf, 100 );
	_buf.insert( _buf.end(), buf, buf + len );
}